#ifndef DATABASE_SETOBJECT_H
#define DATABASE_SETOBJECT_H

#include "Object.hpp"

#include <unordered_map>
#include <functional>
#include <vector>
#include <unordered_set>

namespace DBServer
{
namespace Database
{

class SetObject : public Object {
public:
    using Callback = std::function<void(SetObject&, CommandRequest&&, CommandRespond&)>;

    SetObject()
    :Object(SET_TYPE)
    {}
    ~SetObject() = default;

    void command_excute(CommandRespond& rep, CommandRequest&& req, com_func_t& cft);

public:
    /**
     * the command of SetObject:
     * 1.GET        KEY                 // get all element from set
     * 2.SADD       KEY     VALUE       // add a element into set
     * 3.SSIZE      KEY                 // get the number of the element in set
     * 4.SEXIST     KEY     VALUE       // make sure that the goal is in the set or not
     * 5.SPOP       KEY     VALUE       // delete a element from set
     * 
    */
    inline auto get() -> std::vector<std::string>
    {
        std::vector<std::string> data_list;
        for (auto s : _set)
            data_list.push_back(s);
        return data_list;
    }

    inline auto sadd(std::string&& value) -> bool
    {
        auto iter = _set.find(value);
        if (iter == _set.end()) return false; 
        _set.insert(value); 
        return true;
    }

    inline auto ssize() -> int
    { return _set.size(); }

    inline auto sexist(std::string&& value) -> bool
    { return _set.find(value) == _set.end(); }

    inline auto spop(std::string&& value) -> bool
    { 
        if (!sexist(std::move(std::string(value)))) return false;
        _set.erase(value);
        return true;
    }

private:
    std::unordered_set<std::string> _set;
    static std::unordered_map<int, Callback> cb_table;
};
    
} // namespace Database
} // namespace DBServer


#endif